fix: accept destination dev-branch ancestors in integration history check (PTFE-3343)#271
fix: accept destination dev-branch ancestors in integration history check (PTFE-3343)#271delthas wants to merge 2 commits into
Conversation
…heck (PTFE-3343) When a development branch has not diverged from its parent (it points at the same commit), a manually-resolved integration branch carrying a forced merge commit tripped a false BranchHistoryMismatch. The merge's first parent is the shared development-branch tip, which the `git log A..B` diffs used to build acceptable_parents exclude (the boundary commit is dropped), so the check rejected a parent that legitimately belongs to the target development branch. Accept a merge parent that is an ancestor of the destination development branch (Branch.includes_commit), matching the check's own documented intent. Genuine rebase / force-push detection is preserved.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #271 +/- ##
==========================================
+ Coverage 89.60% 89.62% +0.02%
==========================================
Files 81 81
Lines 10589 10614 +25
==========================================
+ Hits 9488 9513 +25
Misses 1101 1101
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
tcarmet
left a comment
There was a problem hiding this comment.
Nice work! Please add the extra testcase :)
…eck (PTFE-3343) When the destination development branch has not diverged from its parent and the PR's feature branch is behind the shared tip, bert-e auto-creates the integration branch via a real (non-fast-forward) merge whose first parent is the shared dev tip -- the same condition the manual-resolution test covers, but reached through the fully-automated path. Added per review feedback from tcarmet.
| for rev in wbranch_set: | ||
| if not all(p in acceptable_parents for p in rev.parents): | ||
| if not all(p in acceptable_parents or | ||
| wbranch.dst_branch.includes_commit(p) |
There was a problem hiding this comment.
Why includes_commit rather than just adding the dev tip to dst_set (the boundary that .. drops)? I think includes_commit is the better choice , just confirming it's deliberate and that wbranch_set stays small enough that a per-parent merge-base is a non-issue.
| self.gitrepo.cmd('git checkout development/4.3') | ||
| self.gitrepo.cmd('git checkout -b development/4.4') | ||
| self.gitrepo.cmd('git push -u origin development/4.4') |
There was a problem hiding this comment.
Could pull that into a tiny helper (e.g. branch_nondiverged_dev('4.3', '4.4')) so the two tests only differ on the part that matters (manual merge vs late-PR auto-merge). Not blocking tho
Problem
Bert-E raised a false
History mismatch(BranchHistoryMismatch, code 113) — telling the user toreseteven though nothing was rebased — when an integration branch sat on a development branch that had not diverged from its parent (development/X.Yfreshly branched offdevelopment/X.(Y-1), still pointing at the same commitD) and that integration branch carried a real merge commit.When it happens
The trigger is a real (non-fast-forward) merge commit on
w/X.Ywhose first parent is the shared dev tipD. Two ways to get there:D(the PR is behind the dev tip), the auto-createdw/X.Ymerge cannot fast-forward (feature andDare siblings), so Bert-E produces a real merge commit whose first parent isD. PRs are frequently behind the dev tip, so this is the common case. (Thanks @tcarmet for spotting this path.)w/X.Ywith a forced merge commit (e.g.git merge -s ours) so the higher development branch ignores the cascaded change (the ARSN-600 scenario).It does not trigger when the PR is already up-to-date with the dev tip: the merge then fast-forwards and no merge commit is created.
Root cause
update_integration_branches()buildsacceptable_parentsfrom threegit log A..Bdiffs (prev_set,dst_set,wbranch_set).A..Bexcludes the boundary commit, so whendevelopment/X.Y == development/X.(Y-1),dst_setis empty and the shared dev tipD— the first parent of the integration merge — appears in none of the sets. The check then rejects a parent that legitimately belongs to the target development branch, contradicting the check's own documented intent (its comment explicitly allows parents from "the target development branch").Fix
Accept a merge parent that is an ancestor of the destination development branch (
Branch.includes_commit, i.e.git merge-base --is-ancestor), matching the documented intent.Genuine rebase / force-push detection is preserved: a rebased source leaves a merge whose offending parent is a feature-branch commit that is not an ancestor of any development branch, so it still raises. The existing
BranchHistoryMismatchtests still pass. Two failing-first regression tests cover the non-diverged case:test_history_mismatch_nondiverged_dev_branch— manual-resolution pathtest_history_mismatch_nondiverged_dev_auto_integration— auto-created merge of a late PRFull
tox -e tests-noqueueandtox -e testssuites pass (202 tests each).Jira: PTFE-3343